package copyengine.resource.resProxy
{
    import copyengine.log.CELog;
    import copyengine.resource.resProxy.cacheData.CEResCacheDataBasic;
    import copyengine.resource.resProxy.loadQueue.CEResLoadQueue;
    import copyengine.utils.GeneralUtils;

    import flash.utils.Dictionary;

    /**
     * CEResProxy用于加载游戏中用到的所有资源,对于Starling部分则同时支持纹理丢失后的恢复
     *
     * 功能概述:
     *
     * 在外部 Scene,Dialog 进入时候会new出一个新的CEResProxy 用于加载该场景或者对话框的所有资源,当模块退出时候
     * 调用 resProxy.dispose() 方法 其内部会自动判断是否可以释放资源 。如果可以释放则直接释放 Starling中及表现为纹理卸载
     * 因为采用的是引用计数方法,所以可以保证资源的安全(在没有任何引用的情况下才会卸载)。同时也是由于是引用计数方式 所以需要
     * 上层逻辑对resProxy的慎重使用,退出时候一定要dispose 否则会出现引用计数不准确导致的无法释放
     *
     * 使用方法:
     *
     * --未封装的调用方式:
     *
     *  // 手动创建描述文件
     *  var fileDesc:CEResFIleDesc = new CEResFIleDesc()
     *  fileDesc.fileName = "AAA.swf";                                       -->文件名 需要全局唯一不可重复
     *  fileDesc.fileSize = 100;                                                    -->资源大小,单位需要统一 比如字节数 用于进度条的展示
     *  fileDesc.filePath = "./res/AAA.swf";                                 -->资源路径 用于加载资源
     *  fileDesc.fileType = CEResFIleDesc.FILE_TYPE_SWF;         -->用于查找Creator,详情见ICEResCacheDataCreator
     *
     *  // 放入Vector中,因为ResProxy设计的初衷是为了同时加载多个文件
     *  var resVector:Vector.<CEResFIleDesc> = new Vector.<CEResFIleDesc>();
     *  resVector.push(fileDesc);
     *
     *  // 创建加载队列, 加载队列才为ResProxy接受的唯一参数类型
     *  var resQueue:CEResLoadQueue = new CEResLoadQueue();
     *  resQueue.setLoadingData(resVector, onResLoadComplete, null, null);
     *
     *  //创建ResProxy 同时进行相应的加载工作
     *  resProxy = new CEResProxy();
     *  resProxy.loadResInQueue(resQueue);
     *
     *  设计思路:
     *
     *  CEResProxy             --->     最终的门面,上层逻辑直接引用该对象 用于getData() 取数据 dispose() 清除资源引用计数
     *  CEResLoadQueue    --->     负责以队列的方式加载文件,不负责具体的加载工作 仅仅是对 队列的管理
     *  CEResCacheDataBasic  -->  具体的资源引用,每一个资源 比如一个swf或者png都会对应一个CEResCacheDataBasic, 其内部进行
     *                                              1· 资源的加载/释放
     *                                              2· 纹理丢失后的恢复 (Starling)
     *                                              3· 当前资源的引用计数管理
     *                                              4· 获取资源getData()
     *
     *  CEResCachePool        --->   大缓存池,存储所有的CEResCacheDataBasic 虽然是单例 但是外部不应该直接调用
     *
     *  后期扩充:
     *
     *  CEResProxy 以内的部分应该仅仅扩充Creator 用于支持不同类型文件的加载, CE开头的为普通flash部分资源 比如swf png 而CES开头的为Starling部分的支持
     *  比如 Texture 等等, 如果再有扩展 则创建新的Creator并在引擎初始化时候注册进去
     *
     *  对于 延迟加载或者其他扩展功能 应该直接在CEResProxy上面进行二次封装, 比如延迟加载 则应创建 类似于 LazeLoadIcon.as 里面引用一个ResProxy 在加载之前
     *  放置一个Loading元素 再加载后替换. 不应该像之前CE引擎出力的方式 把逻辑放到了CEResCacheDataBasic中
     *
     *
     */
    public final class CEResProxy
    {
        //用Boolean标记,防止被多次调用
        private var mIsDisposed:Boolean = false;

        //缓存所有的LoadQueue队列,当Queue中的文件加在完成后及会释放
        private var mAllLoadQueueVector:Vector.<CEResLoadQueue>;

        //缓存当前ResProxy所加载的所有ResCacheData对象
        //CEResProxy不可以直接操作CEResCachePool,只能通过字典中引用的部分取得相应的资源
        private var mAllResCacheDataDic:Dictionary;

        public function CEResProxy()
        {
            mAllResCacheDataDic = new Dictionary();
            mAllLoadQueueVector = new Vector.<CEResLoadQueue>();
        }

        /**
         * Load 在队列中设置的资源,队列和里面的资源由上层封装类设置
         */
        public function loadResQueue(_queue:CEResLoadQueue):void
        {
            mAllLoadQueueVector.push(_queue);
            _queue.setResProxyLoadFinishCallback(onQueueLoadComplete);
            _queue.start();
        }

        public function getRes(_resName:String):*
        {
            var resReader:CEResCacheDataBasic = mAllResCacheDataDic[_resName];
            if (resReader != null) {
                return resReader.getData();
            } else {
                CELog.err("CEResProxy-> Can't getRes by name:" + _resName + " as current proxy not contain infoTree");
                return null;
            }
        }

        public function dispose():void
        {
            if (!mIsDisposed) {
                mIsDisposed = true;
                for each(var dataReader:CEResCacheDataBasic  in mAllResCacheDataDic) {
                    dataReader.subReferenceCount();
                }
                mAllResCacheDataDic = null;
            }
        }

        //========================//
        //==Private  Function
        //=========================//

        /**
         * 当Queue文件内的资源全部加在完毕后回调CEResProxy让其将自己删除
         * *!! Queue在回调完CEResProxy后会自己回调上层逻辑(及在调用loadRes时候注册的onComplete函数)
         */
        private function onQueueLoadComplete(_queue:CEResLoadQueue, _allCachedDataReaderVector:Vector.<CEResCacheDataBasic>):void
        {
            for each(var resCacheData:CEResCacheDataBasic in _allCachedDataReaderVector) {
                mAllResCacheDataDic[resCacheData.getResName()] = resCacheData;
                resCacheData.addReferenceCount();
            }
            //清除出加载队列
            GeneralUtils.removeElementFromArrayOrVector(_queue, mAllLoadQueueVector);
        }

    }
}